package com.dries.netty.chat.session;

import cn.hutool.core.util.IdUtil;
import com.dries.netty.chat.entity.User;
import com.dries.netty.chat.processer.ChatProcesser;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Dries
 * @email 1451691457@qq.com
 */
@Slf4j
@Data
public class ServerSession {

    public static final AttributeKey<String> KEY_USER_ID = AttributeKey.valueOf("key_user_id");

    public static final AttributeKey<ServerSession> SESSION_KEY = AttributeKey.valueOf("SESSION_KEY");

    /**
     * 用户实现服务端会话管理的核心
     */
    // 通道
    private Channel channel;
    // 用户
    private User user;

    // session 唯一标识
    private final String sessionId;

    private String group;

    // 登陆状态
    private boolean isLogin = false;

    /**
     * session中存储的session 变量属性值
     */
    private Map<String, Object> map = new ConcurrentHashMap<>();

    public ServerSession(Channel channel) {
        this.channel = channel;
        this.sessionId = buildNewSessionId();
        log.info(" ServerSession 绑定会话 " + channel.remoteAddress());
        channel.attr(ServerSession.SESSION_KEY).set(this);
    }

    // 反向导航,根据ChannelHandlerContext 获取用户ServerSession
    public static ServerSession getSession(ChannelHandlerContext ctx) {
        Channel channel = ctx.channel();
        return channel.attr(ServerSession.SESSION_KEY).get();
    }

    // 反向导航,根据channel 获取用户ServerSession
    public static ServerSession getSession(Channel channel) {
        return channel.attr(ServerSession.SESSION_KEY).get();
    }

    /**
     * 获取唯一的sessionId
     */
    private static String buildNewSessionId() {
        return IdUtil.simpleUUID();
    }

    public synchronized void set(String key, Object value) {
        map.put(key, value);
    }

    public synchronized <T> T get(String key) {
        return (T) map.get(key);
    }

    /**
     * 判断是否存在用户信息
     *
     * @return
     */
    public boolean isValid() {
        return getUser() != null;
    }

    public void processError(Throwable error) {

        /**
         * 处理错误，得到处理结果
         */
        String result = ChatProcesser.getSingleInstance().onError(this, error);
        /**
         * 发送处理结果到其他的组内用户
         */
        SessionMap.getSingleInstance().sendToAll(result, this);

        String echo = ChatProcesser.getSingleInstance().onClose(this);
        /**
         * 关闭连接， 关闭前发送一条通知消息
         */
        SessionMap.getSingleInstance().closeSession(this, echo);

    }

}
